package com.ctshk.rpc.order.season.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.train.add.SupplierOrderSystemTrainAddReq;
import com.ctshk.rpc.booking.req.system.train.add.SupplierSystemOrderTrainAddReq;
import com.ctshk.rpc.booking.req.system.train.add.SupplierSystemOrderTrainTicketAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.iotc.dto.OperateBankPreferenceQueryDTO;
import com.ctshk.rpc.iotc.req.OperateBankConformQueryReq;
import com.ctshk.rpc.iotc.service.IOperateBankPreferenceService;
import com.ctshk.rpc.order.season.dto.SeasonOrderPayDTO;
import com.ctshk.rpc.order.season.dto.SeasonOrderTouristDataDTO;
import com.ctshk.rpc.order.season.dto.SeasonProductOrderTrainDTO;
import com.ctshk.rpc.order.season.entity.SeasonOrder;
import com.ctshk.rpc.order.season.entity.SeasonProductOrderTrain;
import com.ctshk.rpc.order.season.mapper.SeasonOrderMapper;
import com.ctshk.rpc.order.season.mapper.SeasonProductOrderTrainMapper;
import com.ctshk.rpc.order.season.service.ISeasonOrderTouristService;
import com.ctshk.rpc.order.season.service.ISeasonProductOrderTrainService;
import com.ctshk.rpc.order.train.req.TrainOrderTouristReq;
import com.ctshk.rpc.order.train.req.TrainPayOrderCollectionReq;
import com.ctshk.rpc.order.train.req.TrainPlaceOrderReq;
import com.ctshk.rpc.order.train.service.ITrainOrderService;
import com.ctshk.rpc.season.service.ISeasonDynamicProductPackageService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.dto.member.CrmAccountDTO;
import com.ctshk.rpc.system.req.crm.member.CrmMemberQueryReq;
import com.ctshk.rpc.system.service.ICrmMemberService;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 套票-订单-火车票订单 服务实现类
 * </p>
 *
 * @author 杨林
 * @since 2021-03-24
 */
@DubboService
public class SeasonProductOrderTrainServiceImpl extends ServiceImpl<SeasonProductOrderTrainMapper, SeasonProductOrderTrain> implements ISeasonProductOrderTrainService {

    @Autowired
    private SeasonProductOrderTrainMapper orderTrainMapper;

    @Autowired
    private SeasonOrderMapper seasonOrderMapper;

    @Autowired
    private ISeasonOrderTouristService seasonOrderTouristService;

    @DubboReference
    private ISupplierOrderService supplierOrderService;

    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private ITrainOrderService trainOrderService;

    @DubboReference
    private ISeasonDynamicProductPackageService packageService;
    @DubboReference
    private ICrmMemberService crmMemberService;
    @DubboReference
    private IOperateBankPreferenceService iOperateBankPreferenceService;

    @Override
    public void saveTrainProduct(List<SeasonProductOrderTrainDTO> trainList, Long userId, Long orderId) {
        LocalDateTime now = LocalDateTime.now();
        List<SeasonProductOrderTrain> list = trainList.stream().map(
                trainReq -> {
                    SeasonProductOrderTrain train = EntityUtil.copy(trainReq, SeasonProductOrderTrain.class);
                    train.setCreateId(userId);
                    train.setGmtCreate(now);
                    train.setIsDeleted(IsDeletedCode.NO.getCode());
                    train.setSeasonOrderId(orderId);
                    train.setId(SnowflakeIdWorker.nextId());
                    return train;
                }
        ).collect(Collectors.toList());

        orderTrainMapper.insertBatchSomeColumn(list);
    }

    /* @MethodName: 获取火车票 订单信息集合
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/30 16:44
     **/
    @Override
    public List<SeasonProductOrderTrainDTO> getOrderTrainList(Long id) {
        List<SeasonProductOrderTrainDTO> resultList = EntityUtil.copyList(
                orderTrainMapper.selectList(
                        new QueryWrapper<SeasonProductOrderTrain>().lambda()
                                .eq(SeasonProductOrderTrain::getSeasonOrderId, id)
                                .eq(SeasonProductOrderTrain::getIsDeleted, IsDeletedCode.NO.getCode())

                ), SeasonProductOrderTrainDTO.class);

        return resultList;
    }

    /* @MethodName: 火车票下供应商预订单
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/7 17:52
     **/
    @Override
    public void playSupplierOrder(Long orderId, TokenUser tokenUser) {
        SeasonOrder seasonOrder = getSeasonOrderById(orderId);
        //旅客信息
        List<SeasonOrderTouristDataDTO> touristList = seasonOrderTouristService.getTouristList(orderId);
        //是否是同一供应商（判读条件 主订单的 供应商id(就是负责人的部门id) 是否与机票一直）
        boolean ifEqualSupplier = true;
        //获取当前用户信息
        UserDTO user = iSysUserService.getUser(new UserDTO().setId(tokenUser.getId()));
        UserDTO chargeDto = iSysUserService.getUser(new UserDTO().setId(seasonOrder.getChargeUserId()));
        Long deptId = chargeDto.getDeptId();
        List<SeasonProductOrderTrainDTO> trainList = getOrderTrainList(orderId);
        if (!CollectionUtils.isEmpty(trainList)) {
            SeasonProductOrderTrainDTO trainDto1 = trainList.get(0);
            if (!trainDto1.getSupplierId().equals(deptId)) {
                ifEqualSupplier = false;
            }
            playSupplierTrainOrder(seasonOrder, touristList, trainList, trainDto1.getSupplierId(), trainDto1.getSupplierName(), user);
            if (!ifEqualSupplier) {//不是同一供应商 再次发起供应商预订单 只是供应商id 不同
                String depName = chargeDto.getDept();
                playSupplierTrainOrder(seasonOrder, touristList, trainList, deptId, depName, user);
            }
        }
    }

    /* @MethodName: 下火车供应商 预订单
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/12 16:06
     **/
    private void playSupplierTrainOrder(SeasonOrder seasonOrder, List<SeasonOrderTouristDataDTO> touristList, List<SeasonProductOrderTrainDTO> trainList, Long supplierId, String supplierName, UserDTO user) {
        SupplierOrderSystemTrainAddReq trainAddReq = new SupplierOrderSystemTrainAddReq();
        SeasonProductOrderTrainDTO trainDTO1 = trainList.get(0);
        //订单类型
        trainAddReq.setOrderType(1);
        //供应商ID不能为空
        trainAddReq.setSupplierId(supplierId);
        //供应商名称
        trainAddReq.setSupplierName(supplierName);
        //供应商订单类型不能为空 1:普通订单,2:内部挂账订单
        trainAddReq.setSupplierOrderType("2");
        //供应商销售编号/部门ID(根据'供应商订单编号'显示，1：供应商销售编号，2：部门ID)
        trainAddReq.setOriginalSaleNumber(String.valueOf(user.getDeptId()));
        //业务类型不能为空
        trainAddReq.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
        //预订类型
        trainAddReq.setReserveTypeId(SupplierReserveTypeEnum.TRAIN.getId());
        //产品类型
        trainAddReq.setProductType(ProductType.MANUAL_ENTRY.getCode());
        //资源所属部门ID
        trainAddReq.setDepartmentId(user.getDeptId());
        //资源所属部门
        trainAddReq.setDepartment(user.getDept());
        //销售单号
        trainAddReq.setSaleNumber(seasonOrder.getOrderNumber());
        //产品编号(通用)
        trainAddReq.setProductNumber(String.valueOf(trainDTO1.getProductId()));
        //产品名称
        trainAddReq.setProductNumber(seasonOrder.getProductName());
        //总金额
        trainAddReq.setTotalFee(seasonOrder.getOrderAmount());
        //币种id
        trainAddReq.setCurrencyId(Currency.HKD.getCode());
        //币种
        trainAddReq.setCurrency(Currency.HKD.getCurrency());
        //应付金额不能为空
        trainAddReq.setPayableAmount(seasonOrder.getReceivableAmount());
        //付款类型ID不能为空
        //trainAddReq.setPayTypeId();
        List<SupplierSystemOrderTrainAddReq> sysTrainList = new LinkedList<>();
        for (SeasonProductOrderTrainDTO trainDTO : trainList) {
            SupplierSystemOrderTrainAddReq orderTrainAddReq = new SupplierSystemOrderTrainAddReq();
            orderTrainAddReq.setOrderId(seasonOrder.getId());
            List<SupplierSystemOrderTrainTicketAddReq> sysList = new LinkedList<>();
            for (SeasonOrderTouristDataDTO dataDto : touristList) {
                SupplierSystemOrderTrainTicketAddReq touristAddReq = new SupplierSystemOrderTrainTicketAddReq();
                touristAddReq.setTouristId(dataDto.getId());
                touristAddReq.setTouristName(dataDto.getTouristName());
                touristAddReq.setTouristTypeId(dataDto.getTouristTypeId());
                touristAddReq.setTouristType(dataDto.getTouristType());
                touristAddReq.setOrderId(seasonOrder.getId());
                touristAddReq.setTrainId(trainDTO.getProductId());
                //touristAddReq.setTravelType(shipDto.getTripType());
                touristAddReq.setGoLocationJson(trainDTO.getDepStationName());
                touristAddReq.setDesLocationJson(trainDTO.getArrStationName());
                touristAddReq.setTrainNumber(trainDTO.getTrainNumber());
                touristAddReq.setStartTime(trainDTO.getDepTime());
                touristAddReq.setLevel(trainDTO.getCabinClass());
                sysList.add(touristAddReq);
            }
            orderTrainAddReq.setSupplierSystemOrderTrainTicketAddReqList(sysList);
            sysTrainList.add(orderTrainAddReq);
        }
        trainAddReq.setSupplierSystemOrderTrainAddReqList(sysTrainList);
        supplierOrderService.addSystemTrain(trainAddReq, user.getId());
    }

    /* @MethodName: 动态套票 下各自订单后 确认对应状态
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/14 10:57
     **/
    @Override
    public void changeAffirmState(Long orderId, Integer isAffirm) {
        UpdateWrapper<SeasonProductOrderTrain> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SeasonProductOrderTrain::getOrderId, orderId);
        updateWrapper.lambda().set(SeasonProductOrderTrain::getScheduledStatus, isAffirm);
        orderTrainMapper.update(null, updateWrapper);
    }

    /* @MethodName: 退款状态
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/20 10:25
     **/
    @Override
    public void changeCancelOrderState(Long orderId, Integer cancelStatus) {
        UpdateWrapper<SeasonProductOrderTrain> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SeasonProductOrderTrain::getOrderId, orderId);
        updateWrapper.lambda().set(SeasonProductOrderTrain::getCancelStatus, cancelStatus);
        orderTrainMapper.update(null, updateWrapper);
    }


    /* @MethodName: 固定套票下单 走 内部挂账形式
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/21 13:56
     **/
    @Override
    public void playInternalOrder(Long orderId, TokenUser user) {

    }


    /* @MethodName: 下火车票订单
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/21 15:39
     **/
    @Override
    public void playTrainOrder(TokenUser user, List<SeasonOrderPayDTO> payList, List<SeasonOrderTouristDataDTO> touristList, Map<String, Object> map) {
        SeasonOrder seasonOrder = (SeasonOrder) map.get("seasonOrder");//获取订单信息
        List<SeasonProductOrderTrainDTO> list = getOrderTrainList(seasonOrder.getId());
        List<Long> orderIds = new ArrayList<>();
        if (null != list && list.size() > 0) {
            for (SeasonProductOrderTrainDTO l : list) {
                BigDecimal totalProductPrice = BigDecimal.ZERO;
                BigDecimal couponDeduction = BigDecimal.ZERO;
               // totalProductPrice.add(trainService.getTrainProductPrice(new ProductPriceReq(l.getProductId(), l.getDepTime().toLocalDate(), EntityUtil.copyList(touristList, PassengerReq.class), user.getId(), null)));
                //火车信息下单
                TrainPlaceOrderReq trainPlaceOrderReq = new TrainPlaceOrderReq();
                trainPlaceOrderReq.setTrainProductId(l.getProductId());//产品
                trainPlaceOrderReq.setEffectiveTime(l.getDepTime());//日期
                trainPlaceOrderReq.setNumber(touristList.size());//票数
                trainPlaceOrderReq.setIsAgent(0);//代理
                trainPlaceOrderReq.setProductType(seasonOrder.getProductType());
                trainPlaceOrderReq.setSource(seasonOrder.getSource());
                trainPlaceOrderReq.setSalesmanId(seasonOrder.getSalesmanId());
                trainPlaceOrderReq.setSalesmanName(seasonOrder.getSalesmanName());
                trainPlaceOrderReq.setSurname(seasonOrder.getSurname());
                trainPlaceOrderReq.setName(seasonOrder.getName());
                trainPlaceOrderReq.setContactName(seasonOrder.getContactName());
                trainPlaceOrderReq.setContactMobile(seasonOrder.getContactMobile());
                trainPlaceOrderReq.setContactMobileAreaCodeId(seasonOrder.getContactMobileAreaCodeId());
                trainPlaceOrderReq.setContactMobileAreaCode(seasonOrder.getContactMobileAreaCode());
                trainPlaceOrderReq.setContactEmail(seasonOrder.getContactEmail());
                trainPlaceOrderReq.setSalesMethods(seasonOrder.getSalesMethods());
                trainPlaceOrderReq.setTrainOrderTouristReqList(EntityUtil.copyList(touristList, TrainOrderTouristReq.class)); //转换旅客信息 并添加
                List<TrainPayOrderCollectionReq> reqList = new ArrayList<>();//付款的集合
                //推广码信息
                boolean couponFlag = (boolean) map.get("couponFlag");//获取推广码使用标识
                if (!couponFlag && StringUtils.isNotBlank(seasonOrder.getCouponCode())) {
                    OperateBankConformQueryReq operateBankConformQueryReq = new OperateBankConformQueryReq();
                    operateBankConformQueryReq.setId(Long.parseLong(seasonOrder.getCouponCode()));//编码
                    operateBankConformQueryReq.setBusinessType(SystemBusinessType.ATTRACTION_TICKET.getCode());//类型
                    operateBankConformQueryReq.setChannelId(1L);//使用渠道，1代表云平台
                    operateBankConformQueryReq.setRelationId(l.getProductId());
                    operateBankConformQueryReq.setTotalPaidIn(totalProductPrice);//价格
                    CrmMemberQueryReq crmMemberQueryReq = new CrmMemberQueryReq();
                    crmMemberQueryReq.setQueryType(1);
                    crmMemberQueryReq.setNumber(String.valueOf(seasonOrder.getMemberId()));
                    CrmAccountDTO crmAccountDTO = crmMemberService.queryAccountDetail(crmMemberQueryReq);
                    operateBankConformQueryReq.setDiscountObjectId((long) crmAccountDTO.getType());
                    Result<OperateBankPreferenceQueryDTO> conform = iOperateBankPreferenceService.queryConform(operateBankConformQueryReq);
                    if (conform.isSuccess()) {
                        map.put("couponFlag", true);
                        trainPlaceOrderReq.setCouponId(Long.parseLong(seasonOrder.getCouponCode()));
                        couponDeduction.add(conform.getData().getReductionAmount());
                        //添加推广码的付款方式
                        TrainPayOrderCollectionReq trainPOCReq = new TrainPayOrderCollectionReq();
                        trainPOCReq.setCollectionWay(PayRefundMethod.TGM.getCode());
                        trainPOCReq.setCollectionAmount(conform.getData().getReductionAmount());
                        reqList.add(trainPOCReq);
                    }
                }
                //积分
                BigDecimal usingPoints = (BigDecimal) map.get("usingPoints");//获取积分使用标识
                if (usingPoints.compareTo(BigDecimal.ZERO) > 0) {
                    //添加积分的付款方式
                    TrainPayOrderCollectionReq trainPOCReq = new TrainPayOrderCollectionReq();
                    if (totalProductPrice.compareTo(usingPoints) >= 0) {
                        map.put("usingPoints", BigDecimal.ZERO);//全部使用了使用则没有了
                        trainPlaceOrderReq.setUsingPoints(usingPoints.multiply(new BigDecimal(100)).intValue());
                        couponDeduction.add(usingPoints);
                        trainPOCReq.setCollectionAmount(usingPoints);
                    } else {
                        map.put("usingPoints", usingPoints.subtract(totalProductPrice));//添加积分使用之后剩余的积分
                        trainPlaceOrderReq.setUsingPoints(totalProductPrice.multiply(new BigDecimal(100)).intValue());
                        couponDeduction.add(totalProductPrice);
                        trainPOCReq.setCollectionAmount(totalProductPrice);
                    }
                    trainPOCReq.setCollectionWay(PayRefundMethod.CRM.getCode());
                    reqList.add(trainPOCReq);
                }
                //去下订单
                Result<Long> addResult = trainOrderService.addOrder(trainPlaceOrderReq, user);
                if (!addResult.isSuccess()) {//下单失败
                    map.put("trainAddOrderResult", addResult);
                    map.put("failFlag", true);
                    return;
                }
                orderIds.add(addResult.getData());
                BigDecimal receivableAmount = totalProductPrice.subtract(couponDeduction);
                //根据支付方式计算价格
                if (receivableAmount.compareTo(BigDecimal.ZERO) >= 0) {
                    boolean isFinal = (boolean) map.get("isFinal");
                    for (SeasonOrderPayDTO pay : payList) {
                        BigDecimal collectionAmount = pay.getCollectionAmount();//当前支付的价格
                        if (collectionAmount.compareTo(BigDecimal.ZERO) == 0) {
                            continue;
                        }
                        TrainPayOrderCollectionReq trainPayOrderReq = EntityUtil.convertBean(pay, TrainPayOrderCollectionReq.class);
                        if (!isFinal) {
                            //门市汇率
                            // BigDecimal marketExchangeRate = packageService.getMarketExchangeRate(pay.getCurrencyId());
                            // BigDecimal payPrice = marketExchangeRate.multiply(collectionAmount);//当前支付的价格转换成港币
                            if (collectionAmount.compareTo(receivableAmount) >= 0) {
                                //  BigDecimal currentPrice = receivableAmount.divide(marketExchangeRate, 2, BigDecimal.ROUND_UP);
                                if (collectionAmount.compareTo(collectionAmount) >= 0) {
                                    //结余之后的价格
                                    pay.setCollectionAmount(BigDecimal.ZERO);
                                } else {
                                    //当前币种的价格
                                    trainPayOrderReq.setCollectionAmount(collectionAmount);
                                    //结余之后的价格
                                    pay.setCollectionAmount(collectionAmount.subtract(collectionAmount));
                                }
                                break;
                            } else {
                                //全部抵扣就变成零
                                pay.setCollectionAmount(BigDecimal.ZERO);
                            }
                        } else {
                            //全部抵扣就变成零
                            pay.setCollectionAmount(BigDecimal.ZERO);
                        }
                        trainPayOrderReq.setSalerId(seasonOrder.getSalesmanId());
                        trainPayOrderReq.setSalerName(seasonOrder.getSalesmanName());
                        reqList.add(trainPayOrderReq);
                    }
                }
                Result payResult = trainOrderService.payOrder(addResult.getData(), reqList, user);
                if (!payResult.isSuccess()) {//支付失败
                    map.put("trainPayOrderResult", payResult);
                    map.put("failFlag", true);
                } else {
                    SeasonProductOrderTrain train = EntityUtil.convertBean(l, SeasonProductOrderTrain.class);
                    Long trainId = SnowflakeIdWorker.nextId();
                    train.setId(trainId);
                    train.setSeasonOrderId(seasonOrder.getId());
                    train.setOrderId(addResult.getData());
                    train.setCancelStatus(1);
                    train.setScheduledStatus(2);
                    orderTrainMapper.insert(train);
                }
            }
            map.put("trainOrderIds", orderIds);
        }
    }

    public SeasonOrder getSeasonOrderById(Long id) {
        return seasonOrderMapper.selectById(id);
    }
}
